home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / finger31.zip / FINGER.C < prev    next >
C/C++ Source or Header  |  1993-03-25  |  20KB  |  647 lines

  1. //
  2. // Finger Version 3.1, a Windows Sockets Finger Client
  3. //
  4. // Copyright 1992, 1993 Network Research Corporation
  5. //
  6. // Permission to use, modify, and distribute this software and its
  7. // documentation for any purpose and without fee is hereby granted, provided
  8. // that the above copyright notice appears in all copies and that both
  9. // that copyright notice and this permission notice appear in supporting
  10. // documentation.  NRC makes no claims as to the suitability of this software
  11. // for any purpose.
  12. //
  13. // Module FINGER provides the user interface for the finger client, and
  14. // depends on NETWRK for TCP/IP network services, and upon DSPLIST
  15. // retrieve and dispose of "display lists".  The display list represents
  16. // the remote finger server's return in a form suitable for scrolling text
  17. // display.  FINGER prompts the user for a host name (or internet address),
  18. // invokes NETWRK to finger the specified host, and paints the window
  19. // client area with the returned display list.  FINGER uses a view
  20. // (a logical window onto a portion of the display list) to render
  21. // that portion of the list which is currently visable.
  22. //
  23. // 02/12/92 Lee Murach     Created.
  24. // 06/19/92 Mark Towfiq    Adapted to Windows Socket draft rev 1.0.
  25. // 09/25/92 Ian Merritt    Adapted for Windows Sockets 1.0B compatability.
  26. // 10/20/92 Lee Murach     Restructured (Ray Duncan-ized) & added scrollbars.
  27. // 12/02/92 Lee Murach     Split FingerHost() into FingerStart() &
  28. //                         FingerFinish(), for NETWORK_ module interface.
  29. // 03/25/93 Lee Murach     Added per-user finger support.
  30. //
  31.  
  32. #include <windows.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <winsock.h>
  36. #include "finger.h"
  37.  
  38. #define MAXTEXT   132
  39. #define THUMBPOS  LOWORD(lParam)    // Win 16
  40.  
  41. typedef struct                      // associates an error code with text
  42. {
  43.    UINT err;
  44.    char *sztext;
  45. } ERRENTRY;
  46.  
  47. int  APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
  48. LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  49. BOOL APIENTRY HostDlgProc(HWND hDlg, UINT wMsg, UINT wParam, LONG lParam);
  50. BOOL FAR APIENTRY AboutDlgProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  51. BOOL InitInstance(HANDLE hInstance, int nCmdShow);
  52. BOOL InitApp(HANDLE hInstance);
  53. LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  54. LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  55. LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  56. LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  57. LONG DoMouseMove(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  58. LONG DoMenuHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  59. LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  60. LONG DoActivate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  61. LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  62. LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  63. LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
  64. VOID Repaint(VOID);
  65. VOID PosView(int nlines);
  66. VOID ReportWSError(UINT Err);
  67. VOID RelScroll(HWND hWnd, int nlines);
  68. VOID SetWinCaption(VOID);
  69. VOID SetScroll(VOID);
  70. VOID ReportWSError(UINT Err);
  71.  
  72. char     szHostName[MAXHOST+1] = "";// name of host to finger
  73. char     szUser[MAXUSER+1] = "";    // query for this user id (can be null)
  74. char     szAppName[] = "Finger";    // application's name
  75. LINEITEM *pLineItems = 0;           // ptr to display list LINEITEMS
  76. int      nLineItems = 0;            // number of items in display list
  77. LINEITEM *pTopLine;                 // pts to topmost displayable LINEITEM
  78. int      nTopLine = 0;              // line number of topmost displayed line
  79. int      nClientLines;              // # of text lines in view
  80. int      CharY;                     // pixel character height
  81. HWND     hFrame;                    // finger main window handle
  82. HMENU    hMenu;                     // main window menu handle
  83. HANDLE   hInst;                     // this instance of finger
  84. HCURSOR  hCursor;                   // current cursor (either wait or normal)
  85. WSADATA  WSAData;                     // windows sockets info return
  86.  
  87. DECODEWORD frameMsgs[] =            // windows messages & handlers
  88. {
  89.    WM_ACTIVATE,   DoActivate,
  90.    WM_CLOSE,      DoClose,
  91.    WM_COMMAND,    DoCommand,
  92.    WM_DESTROY,    DoDestroy,
  93.    WM_MOUSEMOVE,  DoMouseMove,
  94.    WM_PAINT,      DoPaint,
  95.    WM_SIZE,       DoSize,
  96.    WM_VSCROLL,    DoVScroll,
  97.    WM_KEYDOWN,    DoVScroll,
  98. };
  99.  
  100. DECODEWORD menuItems[] =            // menu items & associated handlers
  101. {
  102.    IDM_HOST,      DoMenuHost,
  103.    IDM_EXIT,      DoMenuExit,
  104.    IDM_ABOUT,     DoMenuAbout,
  105. };
  106.  
  107. ERRENTRY wsErrs[] =                 // error text for windows sockets errors
  108. {
  109.    WSAVERNOTSUPPORTED,  "This version of Windows Sockets is not supported",
  110.    WSASYSNOTREADY,      "Windows Sockets is not present or is not responding",
  111. };
  112.  
  113. ERRENTRY finErrs[] =                // finger specific error text
  114. {
  115.    FE_NOPORT,  "Cannot locate port for finger service",
  116.    FE_NOHOST,  "Unrecognized host name",
  117.    FE_NOSOCK,  "Cannot obtain socket for connection",
  118.    FE_NOCONN,  "Cannot connect to remote server",
  119.    FE_NOSEND,  "Cannot send query to remote server",
  120.    FE_NORECV,  "Error occurred during retrieval"
  121. };
  122.  
  123. //
  124. // WinMain -- windows calls this to start the application.
  125. //
  126. int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  127.     LPSTR lpCmdLine, int nCmdShow)
  128. {
  129.    MSG msg;                                  // holds current message
  130.    int err;
  131.  
  132.    hInst = hInstance;                        // save our instance handle
  133.  
  134.    if (!hPrevInstance)                       // if first instance,
  135.       if (!InitApp(hInstance))               // register window classes
  136.       {
  137.          MessageBox(hFrame, "Can't initialize Finger", szAppName,
  138.             MB_ICONSTOP | MB_OK);
  139.          return(FALSE);
  140.       }
  141.  
  142.    if (!InitInstance(hInstance, nCmdShow))   // per instance initialization &
  143.    {                                         // window creation
  144.       MessageBox(hFrame, "Can't initialize Finger", szAppName,
  145.          MB_ICONSTOP | MB_OK);
  146.          return(FALSE);
  147.    }
  148.  
  149.    if (err = WSAStartup(WSVERSION, &WSAData))// register task with
  150.    {                                         // winsock tcp/ip API
  151.       ReportWSError(err);            
  152.       DestroyWindow(hFrame);                 // kill application window &
  153.    }                                         // signal app exit
  154.  
  155.    while (GetMessage(&msg, NULL, 0, 0))      // loop til WM_QUIT
  156.    {
  157.       TranslateMessage(&msg);
  158.       DispatchMessage(&msg);
  159.    }
  160.  
  161.    WSACleanup();                             // disconnect from winsock
  162.    return msg.wParam;                        // return to windows
  163. }
  164.  
  165. //
  166. // InitApp -- initialization for all instances of application.
  167. // Registers main window class.
  168. //
  169. BOOL InitApp(HANDLE hInstance)
  170. {
  171.    WNDCLASS    wndclass;
  172.  
  173.    InitNetApp();  // initializes (per application) network module
  174.  
  175.    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  176.    wndclass.lpfnWndProc   = FrameWndProc;
  177.    wndclass.cbClsExtra    = 0;
  178.    wndclass.cbWndExtra    = 0;
  179.    wndclass.hInstance     = hInstance;
  180.    wndclass.hIcon         = LoadIcon(hInst, "FingerIcon");
  181.    wndclass.hCursor       = NULL;
  182.    wndclass.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  183.    wndclass.lpszMenuName  = "FingerMenu";
  184.    wndclass.lpszClassName = szAppName;
  185.  
  186.    return(RegisterClass(&wndclass));
  187. }
  188.  
  189. //
  190. // InitInstance -- initializes this instance of app, and creates windows.
  191. //
  192. BOOL InitInstance(HANDLE hInstance, int nCmdShow)
  193. {
  194.    HDC hdc;                            // handle of device context
  195.    TEXTMETRIC tm;                      // contains font dimensions
  196.    RECT rect;                          // outer dimensions of window
  197.  
  198.    hFrame = CreateWindow( szAppName, szAppName,
  199.                WS_OVERLAPPEDWINDOW | WS_VSCROLL,
  200.                CW_USEDEFAULT, CW_USEDEFAULT,
  201.                CW_USEDEFAULT, CW_USEDEFAULT,
  202.                NULL, NULL, hInstance, NULL);
  203.  
  204.    if (!hFrame)
  205.       return(FALSE);
  206.  
  207.    hCursor = LoadCursor(NULL, IDC_ARROW);
  208.    hMenu = GetMenu(hFrame);
  209.  
  210.    InitNetInst(hFrame);  // initialize (per instance) the network module
  211.  
  212.    // finger servers assume a fixed font
  213.    hdc = GetDC(hFrame);
  214.    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
  215.    GetTextMetrics(hdc, &tm);
  216.    CharY = tm.tmHeight + tm.tmExternalLeading;
  217.    ReleaseDC(hFrame, hdc);
  218.  
  219.    // set initial window width & height to 50x10 chars
  220.    GetWindowRect(hFrame, &rect);
  221.    MoveWindow( hFrame, rect.left, rect.top,
  222.                65 * tm.tmAveCharWidth + GetSystemMetrics(SM_CXVSCROLL),
  223.                10 * CharY + GetSystemMetrics(SM_CYCAPTION) +
  224.                GetSystemMetrics(SM_CYMENU), FALSE);
  225.  
  226.    ShowWindow(hFrame, nCmdShow);
  227.    UpdateWindow(hFrame);
  228.  
  229.    return(TRUE);
  230. }
  231.  
  232. //
  233. // FrameWndProc -- callback function for application frame (main) window.
  234. // Decodes message and routes to appropriate message handler. If no handler
  235. // found, calls DefWindowProc.
  236. // 
  237. LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  238. {
  239.    int i;
  240.  
  241.    for (i = 0; i < dim(frameMsgs); i++)
  242.    {
  243.       if (wMsg == frameMsgs[i].Code)
  244.          return(*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam);
  245.    }
  246.  
  247.    return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  248. }
  249.  
  250. //
  251. // DoCommand -- demultiplexes WM_COMMAND messages resulting from menu
  252. // selections, and routes to corresponding menu item handler.  Sends back
  253. // any unrecognized messages to windows.
  254. //
  255. LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  256. {
  257.    int i;
  258.  
  259.    for (i = 0; i < dim(menuItems); i++)
  260.    {
  261.       if (wParam == menuItems[i].Code)
  262.          return(*menuItems[i].Fxn)(hWnd, wMsg, wParam, lParam);
  263.    }
  264.  
  265.    return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  266. }
  267.  
  268. //
  269. // DoMenuHost -- handles the "Host..." menu item.  We prompt for a
  270. // Domain Name System (DNS) host name, or a "dotted IP address" (e.g.,
  271. // 129.216.202.5).  The function invokes NETWRK_ module FingerStart()
  272. // routine to initiate a conversation with the finger server on the
  273. // remote host.  NETWRK_, in turn, calls FingerFinish() to signal
  274. // completion.  Note that the "Host..." menu item is disabled while the
  275. // finger operation is in progress.  This prevents the user from
  276. // starting yet another finger before the first is finished; Finger is
  277. // not designed to process simultaneous requests.
  278. //
  279. LONG DoMenuHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  280. {
  281.    FARPROC lpfnProc;
  282.    int ret;
  283.  
  284.    // prompt for the host's domain name or ip address
  285.  
  286.    lpfnProc = MakeProcInstance(HostDlgProc, hInst);
  287.    ret = DialogBox(hInst, szAppName, hWnd, lpfnProc);
  288.    FreeProcInstance(lpfnProc);
  289.  
  290.    if (ret == IDOK && szHostName[0])
  291.    {
  292.       SetCursor(hCursor = LoadCursor(NULL, IDC_WAIT));
  293.       EnableMenuItem(hMenu, IDM_HOST, MF_GRAYED);
  294.       FingerStart();
  295.    }
  296.  
  297.    return(FALSE);
  298. }
  299.  
  300. //
  301. // FingerFinish -- invoked when the finger operation is complete,
  302. // this function updates the display list & repaints the frame window
  303. // client area if the operation was successful.
  304. //
  305. VOID FingerFinish(UINT Err)
  306. {
  307.    if (!Err)
  308.    {
  309.       FreeLineList(pLineItems);                 // dispose old display
  310.       GetDisplayList(&pLineItems, &nLineItems); // list and get new one
  311.  
  312.       SetWinCaption();                          // set win title to host name
  313.       PosView(0);                               // position view to top
  314.       SetScroll();                              // rescale (or delete)
  315.       Repaint();                                // scrollbar & force a repaint
  316.    }
  317.  
  318.    EnableMenuItem(hMenu, IDM_HOST, MF_ENABLED);
  319.    SetCursor(hCursor = LoadCursor(NULL, IDC_ARROW));
  320. }
  321.  
  322. //
  323. // DoMenuExit -- allows close via menu item.  Same as sys menu close.
  324. //
  325. LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  326. {
  327.    SendMessage(hWnd, WM_CLOSE, 0, 0);
  328.    return(FALSE);
  329. }
  330.  
  331. //
  332. // DoMenuAbout -- respond to "About..." menu selection by invoking the
  333. // "About" dialog box.
  334. //
  335. LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  336. {
  337.    WNDPROC lpProcAbout;
  338.  
  339.    lpProcAbout = MakeProcInstance((WNDPROC)AboutDlgProc, hInst);
  340.    DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
  341.    FreeProcInstance(lpProcAbout);
  342.  
  343.    return(FALSE);
  344. }
  345.  
  346. //
  347. // DoDestroy -- posts a WM_QUIT message to the task's win queue, which
  348. // causes the main translate & dispatch loop to exit, and the app to
  349. // terminate.
  350. //
  351. LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  352. {
  353.    PostQuitMessage(0);
  354.    return(FALSE);
  355. }
  356.  
  357. //
  358. // DoClose -- cleans up display list & tells windows to deallocate
  359. // our window.
  360. //
  361. LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  362. {
  363.    FreeLineList(pLineItems);
  364.    DestroyWindow(hWnd);
  365.  
  366.    return(FALSE);
  367. }
  368.  
  369. //
  370. // DoActivate -- grabs the keyboard focus whenever our deminimized window
  371. // is activated.  This is so we can respond to VK_HOME, VK_END, etc.
  372. // virtual keys for scrolling. HIWORD(lParam) is TRUE for minimized, while
  373. // LOWORD(wParam) is FALSE for activation message.
  374. // 
  375. LONG DoActivate(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  376. {
  377.    if (!HIWORD(lParam) && LOWORD(wParam))
  378.       SetFocus(hFrame);
  379.  
  380.    return FALSE;
  381. }
  382.  
  383. //
  384. // DoMouseMove -- resets the cursor back to the current cursor (either
  385. // a wait, or normal cursor) because Windows will otherwise redraw it
  386. // using the window's class.
  387. //
  388. LONG DoMouseMove(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  389. {
  390.    SetCursor(hCursor);
  391.    return(FALSE);
  392. }
  393.  
  394. //
  395. // PosView -- repositions the view relative to the top of the display list.
  396. // The view is a logical "window" onto the display list.  The frame window's
  397. // client area is painted with the view's contents.
  398. //
  399. VOID PosView(int nlines)
  400. {
  401.    LINEITEM *pline;
  402.    int i;
  403.  
  404.    pline = pLineItems;              // root of LINEITEM list
  405.  
  406.    for (i = 0; i < nlines; i++)
  407.    {
  408.       if (!pline)
  409.          break;
  410.       else
  411.          pline = pline->next;
  412.    }
  413.  
  414.    pTopLine = pline;                // ptr to LINEITEM in topmost view line
  415.    nTopLine =+ nlines;              // offset of topmost view line
  416. }
  417.  
  418. //
  419. // DoPaint -- Paint the client area with the contents of the view.
  420. //
  421. LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  422. {
  423.    HDC hdc;                   // scratch device context
  424.    PAINTSTRUCT ps;            // scratch paint structure
  425.    LINEITEM *pline;           // pts to topmost displayable LINEITEM
  426.    int i;
  427.  
  428.    pline = pTopLine;
  429.    hdc = BeginPaint(hWnd, &ps);
  430.  
  431.    for (i = 0; i <= nClientLines; i++)
  432.    {
  433.       if (pline)
  434.       {
  435.          TextOut(hdc, 0, i * CharY, pline->sztext, pline->len);
  436.          pline = pline->next;
  437.       }
  438.       else
  439.          break;
  440.    }
  441.  
  442.    EndPaint(hWnd, &ps);
  443.    return(FALSE);
  444. }
  445.  
  446. //
  447. // Repaint -- force refresh of client window.
  448. // 
  449. VOID Repaint(VOID)
  450. {
  451.    InvalidateRect(hFrame, NULL, TRUE);
  452. }
  453.  
  454. //
  455. // SetScroll -- sets the vertical scroll range to the length of the display
  456. // list.  The Scrollbar disappears when the list fits within the view.
  457. //
  458. VOID SetScroll(VOID)
  459. {
  460.    if (nLineItems > nClientLines)
  461.       SetScrollRange(hFrame, SB_VERT, 0, nLineItems - nClientLines, FALSE);
  462.    else
  463.       SetScrollRange(hFrame, SB_VERT, 0, 0, FALSE);
  464.  
  465.    SetScrollPos(hFrame, SB_VERT, nTopLine, TRUE);
  466. }
  467.  
  468. // number of lines below the bottom of the view.
  469. #define NLINESBELOW (nLineItems - nTopLine - nClientLines)
  470.  
  471. //
  472. // DoVScroll -- process WM_VSCROLL & WM_KEYDOWN for main window.
  473. //
  474. LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  475. {
  476.    switch (LOWORD(wParam))
  477.    {
  478.       case VK_HOME:
  479.       case SB_TOP:
  480.          if (nTopLine > 0)
  481.             RelScroll(hWnd, -nTopLine);
  482.          break;
  483.  
  484.       case VK_END:
  485.       case SB_BOTTOM:
  486.          if (NLINESBELOW)
  487.             RelScroll(hWnd, NLINESBELOW);
  488.          break;
  489.  
  490.       case VK_PRIOR:
  491.       case SB_PAGEUP:
  492.          if (nTopLine > 0)
  493.             RelScroll(hWnd, max(-nClientLines, -nTopLine));
  494.          break;
  495.  
  496.       case VK_NEXT:
  497.       case SB_PAGEDOWN:
  498.          if (NLINESBELOW)
  499.             RelScroll(hWnd, min(nClientLines, NLINESBELOW));
  500.          break;
  501.  
  502.       case VK_UP:
  503.       case SB_LINEUP:
  504.          if (nTopLine > 0)
  505.             RelScroll(hWnd, -1);
  506.          break;
  507.  
  508.       case VK_DOWN:
  509.       case SB_LINEDOWN:
  510.          if (NLINESBELOW)
  511.             RelScroll(hWnd, 1);
  512.          break;
  513.  
  514.       case SB_THUMBTRACK:
  515.          RelScroll(hWnd, THUMBPOS - nTopLine);
  516.          break;
  517.    }
  518.  
  519.    SetScrollPos(hFrame, SB_VERT, nTopLine, TRUE);
  520.    return(FALSE);
  521. }
  522.  
  523. //
  524. // RelScroll -- scroll up/down nlines from present position
  525. //
  526. VOID RelScroll(HWND hWnd, int nlines)
  527. {
  528.    PosView(nTopLine + nlines);
  529.    ScrollWindow(hWnd, 0, -nlines * CharY, NULL, NULL);
  530.    UpdateWindow(hWnd);
  531. }
  532.  
  533. //
  534. // DoSize -- respond to WM_SIZE by recalculating the number of text lines
  535. // in the main window's client area.
  536. //
  537. LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  538. {
  539.    nClientLines = HIWORD(lParam) / CharY;
  540.    PosView(0);
  541.    SetScroll();
  542.  
  543.    return(FALSE);
  544. }
  545.  
  546. //
  547. // SetWinCaption -- set the frame window caption according to last
  548. // host fingered.
  549. //
  550. VOID SetWinCaption(VOID)
  551. {
  552.    char szcaption[80];
  553.    
  554.    strcpy(szcaption, szAppName);
  555.    strcat(szcaption, " - ");
  556.    strcat(szcaption, szHostName);
  557.  
  558.    SetWindowText(hFrame, szcaption);
  559. }
  560.  
  561. //
  562. // ReportWSError -- prompt user with a windows sockets error message.
  563. //
  564. VOID ReportWSError(UINT Err)
  565. {
  566.    int i;
  567.    char szerr[40];
  568.  
  569.    for (i = 0; i < dim(wsErrs); i++)
  570.    {
  571.       if (Err == wsErrs[i].err)
  572.       {
  573.          MessageBox(hFrame, wsErrs[i].sztext, szAppName,
  574.             MB_ICONSTOP | MB_OK);
  575.          return;
  576.       }
  577.    }
  578.  
  579.    wsprintf(szerr, "Windows Sockets reports error %04x", Err);
  580.    MessageBox(hFrame, szerr, szAppName, MB_ICONSTOP | MB_OK);
  581. }
  582.  
  583. //
  584. // ReportFingerErr -- prompt user with a finger specific error
  585. //
  586. VOID ReportFingerErr(UINT Err)
  587. {
  588.    int i;
  589.  
  590.    for (i = 0; i < dim(finErrs); i++)
  591.    {
  592.       if (Err == finErrs[i].err)
  593.       {
  594.          MessageBox(hFrame, finErrs[i].sztext, szAppName,
  595.             MB_ICONSTOP | MB_OK);
  596.          return;
  597.       }
  598.    }
  599.  
  600.    MessageBox(hFrame, "Unrecognized finger error", szAppName,
  601.       MB_ICONSTOP | MB_OK);
  602. }
  603.  
  604. //
  605. // HostDlgProc -- dialog box proc for "host dialog".
  606. // This box queries user for a host name in response to the user's
  607. // selection of the "Host..." main menu item.
  608. //
  609. BOOL APIENTRY HostDlgProc(HWND hDlg, UINT wMsg, UINT wParam, LONG lParam)
  610. {
  611.    switch(wMsg)
  612.    {
  613.       case WM_INITDIALOG:
  614.          SetDlgItemText(hDlg, IDC_HOSTNAME, szHostName);
  615.          SetDlgItemText(hDlg, IDC_USER, szUser);
  616.          return TRUE;
  617.  
  618.       case WM_COMMAND:
  619.          switch(wParam)
  620.          {
  621.             case IDOK:
  622.                GetDlgItemText(hDlg, IDC_HOSTNAME, szHostName, MAXHOST);
  623.                GetDlgItemText(hDlg, IDC_USER, szUser, MAXUSER);
  624.                EndDialog(hDlg, IDOK);
  625.                return TRUE;
  626.  
  627.             case IDCANCEL:
  628.                EndDialog(hDlg, IDCANCEL);
  629.                return TRUE;
  630.          }
  631.          break;
  632.    }
  633.  
  634.    return FALSE;
  635. }
  636.  
  637. //
  638. // AboutDlgProc -- callback for the "About" dialog box
  639. //
  640. BOOL FAR APIENTRY AboutDlgProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  641. {
  642.    if ((wMsg == WM_COMMAND) && (wParam == IDOK))   // dismiss dialog if OK
  643.       EndDialog(hWnd, 0);
  644.  
  645.    return(FALSE);                                  // otherwise just sit there
  646. }
  647.